package servidor;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.StringTokenizer;
import servgui.*;

public class Servidor implements Runnable {

    private Socket socket;
    private ServidorMultThread servidor;
    private String nick;
    private BufferedReader entrada;
    private PrintWriter saida;
    int numSalas=0;

    public Servidor(Socket socket, ServidorMultThread pai) {
        this.socket = socket;
        this.servidor = pai;
    }

    @Override
    public void run() {
        try {
            String str = new String();
            //Cria um BufferedReader para o canal da stream de entrada de dados do socket s  
            entrada = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            saida = new PrintWriter(socket.getOutputStream(), true);
            //Aguarda por algum dado e imprime a linha recebida quando recebe  
            while ((str = entrada.readLine()) != null) {
                servidor.printMessage(str);
                processStr(str);
                Thread.sleep(5);
            }

            //trata possíveis excessões de input/output. Note que as excessões são as mesmas utilizadas para as classes de java.io      
        } catch (IOException e) {
            servidor.disconnect(this);
            servidor.printMessage("a" + e.getMessage());

        } catch (InterruptedException e2) {
            servidor.printMessage("ba" + e2.getMessage());
        }
    }

    private void processStr(String str) {
        int x;
        String splitedStr[] = str.split(":");
        if (splitedStr[0].compareTo("SERVERCONNECT") == 0) {  //SERVIDORCONNECT:{nick=""}
            x = getConnectByStr(splitedStr[1]);
            if (x == 0) {
                saida.println("SERVERCONNECT:{status=\"Accept\"}");
            } else {
                saida.println("SERVERCONNECT:{status=\"Refuse\",errorNum=\"-1\"}");
            }
        } else {
            if (servidor.isConnected(this) == -1) {
                saida.println(splitedStr[0] + ":{status=\"Refuse\",errorNum=\"-10\"}");   //ErrorNum = -10 -> Cliente não conectado
            } else if (splitedStr[0].compareTo("MESSAGE") == 0) { //MESSAGE:{msg="",toUser=""}
                x = getMessageByStr(splitedStr[1]);
                if (x == 0) {
                    saida.println("MESSAGEFAIL:{status=\"Accept\"}");
                } else {
                    saida.println("MESSAGEFAIL:{status=\"Refuse\",errorNum=\"" + x + "\"}");
                }
                //-1 Usuario destino, não existe
                //-2 Canal destino, não existe
            } else if (splitedStr[0].compareTo("CREATECHANNEL") == 0) { //CREATECHANNEL:{name="#"}
                x = createChannelByStr(splitedStr[1]);
                if (x == 0) {
                    saida.println("CREATECHANNEL:{status=\"Accept\"}");
                } else if (x == -1) {
                    saida.println("CREATECHANNEL:{status=\"Refuse\",errorNum=\"-1\"}");
                }
            } else if (splitedStr[0].compareTo("JOINCHANNEL") == 0) { //JOINCHANNEL:{name="#"}
                x = joinChannelByStr(splitedStr[1]);
                if (x == 0) {
                    saida.println("JOINCHANNEL:{status=\"Accept\"}");
                } else {
                    saida.println("JOINCHANNEL:{status=\"Accept\",errorNum=\"" + x + "\"}");
                    //-1 Ja esta na sala
                    //-2 Sala não existe
                }
            } else if (splitedStr[0].compareTo("DISCONNECTUSER") == 0) { //DISCONNECTUSER:{}
                x = disconnectUserByStr();
                saida.append("DICONNECTUSER:{status=\"Accept\"}");
            } else if (splitedStr[0].compareTo("CHANGENICK") == 0) { //CHANGENICK:{toNick=""}
                x = changeNickByStr(splitedStr[1]);
                if (x == 0) {
                    saida.println("CHANGENICK:{status=\"Accept\"}");
                } else if (x == -1) {
                    saida.println("CHANGENICK:{status=\"Refuse\",errorNum=\"-1\"}");
                }
                //-1 Nick já sendo usado.
            }
        }
    }

    private int changeNickByStr(String str) {
        str = str.substring(1, str.length() - 1);
        String splitedStr[] = str.split("=");
        if (splitedStr[0].compareToIgnoreCase("toNick") == 0) {
            if (servidor.isNickAlreadyUsed(splitedStr[1]) == true) {
                return -1;
            } else {
                this.nick = splitedStr[1];
                return 0;
            }

        }
        return -2;
    }

    private int disconnectUserByStr() {
        servidor.disconnect(this);
        return 0;
    }

    private int joinChannelByStr(String str) { //JOINCHANNEL:{name="#"}
        int x = 0;
        str = str.substring(1, str.length() - 1);
        String splitedStr[] = str.split("=");
        if (splitedStr[0].compareToIgnoreCase("name") == 0) {
            x= servidor.joinChannel(splitedStr[1], this);
            if (x==0) {
                numSalas++;
            }
            return x;
        }
        return 0;
    }

    public int getNumSalas() {
        return numSalas;
    }
    private int createChannelByStr(String str) { //CREATECHANNEL:{name="#"}
        str = str.substring(1, str.length() - 1);
        String splitedStr[] = str.split("=");
        if (splitedStr[0].compareToIgnoreCase("name") == 0) {
            return servidor.createChannel(splitedStr[1], false);
        }
        return -2;
    }

    private int getConnectByStr(String str) {
        nick = getNickByStr(str);
        return servidor.connect(this);
    }

    private String getNickByStr(String str) {
        StringTokenizer st = new StringTokenizer(str);
        String nick = st.nextToken("=");
        nick = st.nextToken("=");
        nick = nick.substring(0, nick.length() - 1);
        return nick;
    }

    private int getMessageByStr(String str) { //TODO //{msg="",toUser=""}
        String processStr = str.substring(1, str.length() - 1);
        String splitedStr[] = processStr.split(",");
        String msg = "", toUser = "";
        for (int i = 0; i < splitedStr.length; i++) {
            String splitedStr2[] = splitedStr[i].split("=");
            if (splitedStr2[0].compareToIgnoreCase("msg") == 0) {
                msg = splitedStr2[1];
            }
            if (splitedStr2[0].compareToIgnoreCase("toUser") == 0) {
                toUser = splitedStr2[1];
            }
        }
        if (toUser.charAt(1) == '#') {
            Channel chan = servidor.searchChannel(toUser);
            if (chan == null) {
                return -2; //-2 Channel don't exist
            }
            chan.sendMessage(msg, this);
            return 0;
        } else {
            Servidor user = servidor.getUserByNick(toUser);
            if (user == null) {
                return -1; //User don't exist
            }

            user.sendMessage(msg, this);
        }
        return 0;
    }

    public void sendMessage(String msg, Servidor fromUser) {
        //TODO
        //"MESSAGE:{msg="",fromUser=""}"
        //Criarar padrao de envio de mensagens
        saida.println("MESSAGE:{msg=" + msg + ",fromUser=" + (fromUser == null ? "ADMIN" : fromUser.getNick()) + "}");
    }

    public String getNick() {
        return nick;
    }
}